home *** CD-ROM | disk | FTP | other *** search
/ Greenhouse Effect Detection Expriment / NASA Greenhouse Effect Detection Expriment 1992 - Disc 2.iso / software / dos / cdf22pc / src / tools / cdfcmp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-03-04  |  45.9 KB  |  1,651 lines

  1. /******************************************************************************
  2. *
  3. *  NSSDC/CDF                        CDFcompare (differences).
  4. *
  5. *  Version 2.0, 4-Mar-92, ST Systems (STX)
  6. *
  7. *  Modification history:
  8. *
  9. *   V1.0   1-Jun-91, J Love    Original version (for CDF V2.1).
  10. *   V1.1  25-Jun-91, J Love    CDF_EPOCH added as a data type.  Added QOP.
  11. *                Added PageInst.
  12. *   V1.2   6-Aug-91, J Love    TRUE/FALSE.  Use 'Exit'/'ExitBAD'.  Use
  13. *                'CDFlib'.  Display message if no differences
  14. *                found.
  15. *   V1.3  10-Aug-91, J Love    Optimized comparison of variable values.
  16. *   V2.0   4-Mar-92, J Love    IBM PC & HP port.
  17. *
  18. ******************************************************************************/
  19.  
  20. #include <stdlib.h>
  21. #include <stdio.h>
  22. #include <string.h>
  23.  
  24. #include "cdfdist.h"
  25. #include "cdfcmp.h"
  26.  
  27. /******************************************************************************
  28. * Global variables.
  29. ******************************************************************************/
  30.  
  31. static CDFid    id1, id2;
  32. static long    numDims1, numDims2;
  33. static long    dimSizes1[CDF_MAX_DIMS], dimSizes2[CDF_MAX_DIMS];
  34. static long    encoding1, encoding2;
  35. static long    majority1, majority2;
  36. static long    format1, format2;
  37. static char    copyright1[CDF_COPYRIGHT_LEN], copyright2[CDF_COPYRIGHT_LEN];
  38. static long    numVars1, numVars2;
  39. static long    numAttrs1, numAttrs2;
  40. static long    maxRec1, maxRec2;
  41. static long    version1, version2;
  42. static long    release1, release2;
  43. static long    increment1, increment2;
  44. static long    attrScope1, attrScope2;
  45. static long    attrMaxEntry1, attrMaxEntry2;
  46. static long    attrNumEntries1, attrNumEntries2;
  47. static long    varMaxRec1, varMaxRec2;
  48. static long    varDataType1, varDataType2;
  49. static long    varNumElems1, varNumElems2;
  50. static long    varRecVary1, varRecVary2;
  51. static long    varDimVarys1[CDF_MAX_DIMS], varDimVarys2[CDF_MAX_DIMS];
  52. static long    varExtendRecs1, varExtendRecs2;
  53. static Boolean    mLog;
  54. static Boolean    cmpNumbers;
  55. static Boolean    cmpVars;
  56. static Boolean    cmpAttrs;
  57. static long    *attrNumMatches1, *attrNumMatches2;
  58. static long    *varNumMatches1, *varNumMatches2;
  59. static Boolean    diffFound;
  60.  
  61. /******************************************************************************
  62. * main (CDFcompare).
  63. ******************************************************************************/
  64.  
  65. #if defined(vms)
  66. main (argc, argv)
  67. #else
  68. void main (argc, argv)
  69. #endif
  70. int argc;
  71. char *argv[];
  72. {
  73. char CDFspec1[MAX_PATH_LEN + 1], CDFspec2[MAX_PATH_LEN + 1];
  74. char CDFspec1t[MAX_PATH_LEN + 1], CDFspec2t[MAX_PATH_LEN + 1];
  75. char **dirs1, **dirs2;
  76. char **CDFs1, **CDFs2;
  77. int numCDFs1, numCDFs2;
  78. char CDFpath1[MAX_PATH_LEN + 1], CDFpath2[MAX_PATH_LEN + 1];
  79. char dir1[MAX_DIR_LEN + 1], dir2[MAX_DIR_LEN + 1];
  80. char CDF1[MAX_NAME_LEN + 1], CDF2[MAX_NAME_LEN + 1];
  81. int i, j;
  82. Boolean match;
  83. long count;
  84. QOP *qop;
  85. static char *validQuals[] = { "log", "nolog", "attr", "noattr", "var", "novar",
  86.                   "number", "nonumber", NULL };
  87. static int optRequired[] = { FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
  88.                  FALSE, FALSE, 0 };
  89.  
  90. static char *instructions[] = {
  91. #if defined(vms)
  92. "Usage:         $ CDFCOMPARE [/[no]LOG] [/[no]ATTR] [/[no]VAR] [/[no]NUMBER]",
  93. "                            <cdf-spec-1> <cdf-spec-2>",
  94. #endif
  95. #if defined(unix)
  96. "Usage:         % cdfcompare [-[no]log] [-[no]attr] [-[no]var] [-[no]number]",
  97. "                            <cdf-spec-1> <cdf-spec-2>",
  98. #endif
  99. #if defined(__MSDOS__)
  100. "Usage:         > cdfcompare [-[no]log] [-[no]attr] [-[no]var]",
  101. "                            [-[no]number]",
  102. "                            <cdf-spec-1> <cdf-spec-2>",
  103. #endif
  104. "",
  105. "Purpose:       CDFcompare displays the differences in two CDFs.  More than",
  106. "               one pair of CDFs may be compared.",
  107. "",
  108. "Parameter(s):  <cdf-spec-1>",
  109. "               <cdf-spec-2>",
  110. "                  The specifications of the CDFs to be compared (do not",
  111. "                  enter extensions).  These can be either a pathname",
  112. "                  specifying a single CDF or a directory/wildcard path",
  113. "                  specifying more than one CDF.  Wildcards are allowed in",
  114. "                  the CDF name but not in the directory path.  The available",
  115. "                  wildcards are similar to those on the operating system",
  116. "                  being used.",
  117. "",
  118. "                  If two directory/wildcard paths are specified, all of the",
  119. "                  CDFs with matching names will be compared.  If a CDF",
  120. "                  pathname and a directory/wildcard path are specified,",
  121. "                  the CDF specified will be compared with the CDF in the",
  122. "                  directory/wildcard path having the same name.  If two CDF",
  123. "                  pathnames are specified, the CDFs are compared (this is",
  124. "                  the only way to compare two CDFs having different names).",
  125. "",
  126. #if defined(vms)
  127. "Qualifier(s):  /[no]LOG",
  128. #endif
  129. #if defined(unix) | defined(__MSDOS__)
  130. "Qualifier(s):  -[no]log",
  131. #endif
  132. "                  Specifies whether or not progress of the comparison is",
  133. "                  displayed.  The default is logging disabled.",
  134. "",
  135. #if defined(vms)
  136. "               /[no]ATTR",
  137. #endif
  138. #if defined(unix) | defined(__MSDOS__)
  139. "               -[no]attr",
  140. #endif
  141. "                  Specifies whether or not attributes are to be compared.",
  142. "                  The default is to compare attributes.",
  143. "",
  144. #if defined(vms)
  145. "               /[no]VAR",
  146. #endif
  147. #if defined(unix) | defined(__MSDOS__)
  148. "               -[no]var",
  149. #endif
  150. "                  Specifies whether or not variables are to be compared.",
  151. "                  The default is to compare variables.",
  152. "",
  153. #if defined(vms)
  154. "               /[no]NUMBER",
  155. #endif
  156. #if defined(unix) | defined(__MSDOS__)
  157. "               -[no]number",
  158. #endif
  159. "                  Specifies whether or not numbering differences of",
  160. "                  attributes and variables should be displayed.  The",
  161. "                  default is not to display numbering differences.",
  162. "",
  163. #if defined(vms)
  164. "Example(s):    $ CDFCOMPARE GISS_WETL GISS_WETLX",
  165. "               $ CDFCOMPARE/LOG/NOATTR/NUMBER GISS_WETL CDF$SMPL:GISS_WETLX",
  166. "               $ CDFCOMPARE/VAR CDF$SMPL:QST* [.TEMP]",
  167. "               $ CDFCOMPARE NCDS$DATA:CAC_SST_BLENDED [-.CAC]",
  168. #endif
  169. #if defined(unix)
  170. "Example(s):    % cdfcompare giss_wetl giss_wetlx",
  171. "               % cdfcompare -log -noattr -number giss_wetl ../../giss_wetlx",
  172. "               % cdfcompare -var '${CDF$SMPL}/QST*' temp",
  173. "               % cdfcompare ~ncds/cac_sst_blended ../cac",
  174. #endif
  175. #if defined(__MSDOS__)
  176. "Example(s):    > cdfcompare gisswetl gwetlx",
  177. "               > cdfcompare -log -noattr -number gisswetl ..\\..\\gwetlx",
  178. "               > cdfcompare -var c:\\cdf\\samples\\QST* temp",
  179. "               > cdfcompare b:\\ncds\\cac_sst ..\\cac",
  180. #endif
  181. NULL };
  182.  
  183. /******************************************************************************
  184. * Get qualifiers/options/parameters.
  185. ******************************************************************************/
  186.  
  187. switch (argc == 1) {
  188.   case 1:
  189.     PageInst (instructions);
  190.     Exit;
  191.   default:
  192.     qop = Qop (argc, argv, validQuals, optRequired);
  193.     if (qop == NULL) ExitBAD;
  194.  
  195.     switch (qop->Nparms) {
  196.       case 0:
  197.       case 1:
  198.         printf ("Missing parameter(s).\n");
  199.         ExitBAD;
  200.       case 2:
  201.         strcpy (CDFspec1, qop->parms[0]);
  202.         strcpy (CDFspec2, qop->parms[1]);
  203. #if defined(vms) | defined(__MSDOS__)
  204.     Upcase (CDFspec1);
  205.     Upcase (CDFspec2);
  206. #endif
  207.       break;
  208.       default:
  209.     printf ("Too many parameters.\n");
  210.     ExitBAD;
  211.   }
  212.  
  213.     count = 0;
  214.     if (qop->qualEntered[0]) count++;
  215.     if (qop->qualEntered[1]) count++;
  216.  
  217.     switch (count) {
  218.       case 0:
  219.     mLog = FALSE;
  220.     break;
  221.       case 1:
  222.     if (qop->qualEntered[0])
  223.       mLog = TRUE;
  224.     else
  225.       mLog = FALSE;
  226.     break;
  227.       case 2:
  228.     printf ("Conflicting qualifiers\n");
  229.     ExitBAD;
  230.     break;
  231.     }
  232.  
  233.     count = 0;
  234.     if (qop->qualEntered[2]) count++;
  235.     if (qop->qualEntered[3]) count++;
  236.  
  237.     switch (count) {
  238.       case 0:
  239.     cmpAttrs = TRUE;
  240.     break;
  241.       case 1:
  242.     if (qop->qualEntered[2])
  243.       cmpAttrs = TRUE;
  244.     else
  245.       cmpAttrs = FALSE;
  246.     break;
  247.       case 2:
  248.     printf ("Conflicting qualifiers\n");
  249.     ExitBAD;
  250.     break;
  251.     }
  252.  
  253.     count = 0;
  254.     if (qop->qualEntered[4]) count++;
  255.     if (qop->qualEntered[5]) count++;
  256.  
  257.     switch (count) {
  258.       case 0:
  259.     cmpVars = TRUE;
  260.     break;
  261.       case 1:
  262.     if (qop->qualEntered[4])
  263.       cmpVars = TRUE;
  264.     else
  265.       cmpVars = FALSE;
  266.     break;
  267.       case 2:
  268.     printf ("Conflicting qualifiers\n");
  269.     ExitBAD;
  270.     break;
  271.     }
  272.  
  273.     count = 0;
  274.     if (qop->qualEntered[6]) count++;
  275.     if (qop->qualEntered[7]) count++;
  276.  
  277.     switch (count) {
  278.       case 0:
  279.     cmpNumbers = FALSE;
  280.     break;
  281.       case 1:
  282.     if (qop->qualEntered[6])
  283.       cmpNumbers = TRUE;
  284.     else
  285.       cmpNumbers = FALSE;
  286.     break;
  287.       case 2:
  288.     printf ("Conflicting qualifiers\n");
  289.     ExitBAD;
  290.     break;
  291.     }
  292.     break;
  293. }
  294.  
  295. /******************************************************************************
  296. * Compare the CDFs.
  297. ******************************************************************************/
  298.  
  299. strcpy (CDFspec1t, CDFspec1);
  300. strcat (CDFspec1t, ".cdf");
  301.  
  302. strcpy (CDFspec2t, CDFspec2);
  303. strcat (CDFspec2t, ".cdf");
  304.  
  305. if ( ! IsReg(CDFspec1t)) {
  306.   if ( ! IsReg(CDFspec2t)) {
  307.     /**************************************************************************
  308.     * Both specifications are directories/wildcards.
  309.     **************************************************************************/
  310.  
  311.     if (IsDir(CDFspec1))
  312.       AppendToDir (CDFspec1, "*.cdf");
  313.     else
  314.       strcat (CDFspec1, ".cdf");
  315.  
  316.     numCDFs1 = DirList (CDFspec1, &dirs1, &CDFs1);
  317.  
  318.     if (IsDir(CDFspec2))
  319.       AppendToDir (CDFspec2, "*.cdf");
  320.     else
  321.       strcat (CDFspec2, ".cdf");
  322.  
  323.     numCDFs2 = DirList (CDFspec2, &dirs2, &CDFs2);
  324.  
  325.     if (numCDFs1 > 0)
  326.       if (numCDFs2 > 0) {
  327.     RemoveExtensions (numCDFs1, CDFs1);
  328.     RemoveExtensions (numCDFs2, CDFs2);
  329.  
  330.     match = FALSE;
  331.  
  332.     for (i = 0; i < numCDFs1; i++)
  333.        for (j = 0; j < numCDFs2; j++) {
  334.           if (strcmp(CDFs1[i],CDFs2[j]) == 0) {
  335.         match = TRUE;
  336.  
  337.         strcpy (CDFpath1, dirs1[i]);
  338.         AppendToDir (CDFpath1, CDFs1[i]);
  339.  
  340.         strcpy (CDFpath2, dirs2[j]);
  341.         AppendToDir (CDFpath2, CDFs2[j]);
  342.  
  343.         CompareCDFs (CDFpath1, CDFpath2);
  344.         CleanupComparison ();
  345.  
  346.         break;
  347.           }
  348.        }
  349.  
  350.     if ( ! match) printf ("No matching CDFs found.\n");
  351.       }
  352.       else
  353.     printf ("No CDFs found for second specification.\n");
  354.     else
  355.       if (numCDFs2 > 0)
  356.     printf ("No CDFs found for first specification.\n");
  357.       else
  358.     printf ("No CDFs for either specification.\n");
  359.   }
  360.   else {
  361.     /**************************************************************************
  362.     * First specification is a directory/wildcard, second is a CDF path.
  363.     **************************************************************************/
  364.  
  365.     if (IsDir(CDFspec1))
  366.       AppendToDir (CDFspec1, "*.cdf");
  367.     else
  368.       strcat (CDFspec1, ".cdf");
  369.  
  370.     numCDFs1 = DirList (CDFspec1, &dirs1, &CDFs1);
  371.  
  372.     if (numCDFs1 > 0) {
  373.       RemoveExtensions (numCDFs1, CDFs1);
  374.       ParsePath (CDFspec2, dir2, CDF2);
  375.  
  376.       match = FALSE;
  377.  
  378.       for (i = 0; i < numCDFs1; i++)
  379.      if (strcmp(CDFs1[i],CDF2) == 0) {
  380.        match = TRUE;
  381.  
  382.        strcpy (CDFpath1, dirs1[i]);
  383.        AppendToDir (CDFpath1, CDFs1[i]);
  384.  
  385.        CompareCDFs (CDFpath1, CDFspec2);
  386.        CleanupComparison ();
  387.  
  388.        break;
  389.      }
  390.  
  391.       if ( ! match) printf ("Matching CDF not found.\n");
  392.     }
  393.     else
  394.       printf ("No CDFs found for specification.\n");
  395.   }
  396. }
  397. else {
  398.   if ( ! IsReg(CDFspec2t)) {
  399.     /**************************************************************************
  400.     * First specification is a CDF path, second is a directory/wildcard.
  401.     **************************************************************************/
  402.  
  403.     if (IsDir(CDFspec2))
  404.       AppendToDir (CDFspec2, "*.cdf");
  405.     else
  406.       strcat (CDFspec2, ".cdf");
  407.  
  408.     numCDFs2 = DirList (CDFspec2, &dirs2, &CDFs2);
  409.  
  410.     if (numCDFs2 > 0) {
  411.       RemoveExtensions (numCDFs2, CDFs2);
  412.       ParsePath (CDFspec1, dir1, CDF1);
  413.  
  414.       match = FALSE;
  415.  
  416.       for (i = 0; i < numCDFs2; i++)
  417.      if (strcmp(CDF1,CDFs2[i]) == 0) {
  418.        match = TRUE;
  419.  
  420.        strcpy (CDFpath2, dirs2[i]);
  421.        AppendToDir (CDFpath2, CDFs2[i]);
  422.  
  423.        CompareCDFs (CDFspec1, CDFpath2);
  424.        CleanupComparison ();
  425.  
  426.        break;
  427.      }
  428.  
  429.       if ( ! match) printf ("Matching CDF not found.\n");
  430.     }
  431.     else
  432.       printf ("No CDFs found for specification.\n");
  433.   }
  434.   else {
  435.     /**************************************************************************
  436.     * Both specifications are CDF paths.
  437.     **************************************************************************/
  438.  
  439.     CompareCDFs (CDFspec1, CDFspec2);
  440.     CleanupComparison ();
  441.   }
  442. }
  443.  
  444. Exit;
  445. }
  446.  
  447. /******************************************************************************
  448. * CompareCDFs.
  449. ******************************************************************************/
  450.  
  451. Boolean CompareCDFs (CDFpath1, CDFpath2)
  452. char *CDFpath1;
  453. char *CDFpath2;
  454. {
  455. CDFstatus status;
  456.  
  457. /******************************************************************************
  458. * Open CDFs.
  459. ******************************************************************************/
  460.  
  461. printf ("Comparing \"%s\" with \"%s\"\n", CDFpath1, CDFpath2);
  462.  
  463. diffFound = FALSE;
  464.  
  465. status = CDFlib (OPEN_, CDF_, CDFpath1, &id1,
  466.          GET_, CDF_NUMDIMS_, &numDims1,
  467.                CDF_DIMSIZES_, dimSizes1,
  468.                CDF_ENCODING_, &encoding1,
  469.                CDF_MAJORITY_, &majority1,
  470.                CDF_FORMAT_, &format1,
  471.                CDF_COPYRIGHT_, copyright1,
  472.                CDF_NUMVARS_, &numVars1,
  473.                CDF_NUMATTRS_, &numAttrs1,
  474.                CDF_MAXREC_, &maxRec1,
  475.                CDF_VERSION_, &version1,
  476.                CDF_RELEASE_, &release1,
  477.                CDF_INCREMENT_, &increment1,
  478.          NULL_);
  479. if (! StatusHandler("CDF1",status)) return FALSE;
  480.  
  481. status = CDFlib (OPEN_, CDF_, CDFpath2, &id2,
  482.          GET_, CDF_NUMDIMS_, &numDims2,
  483.                CDF_DIMSIZES_, dimSizes2,
  484.                CDF_ENCODING_, &encoding2,
  485.                CDF_MAJORITY_, &majority2,
  486.                CDF_FORMAT_, &format2,
  487.                CDF_COPYRIGHT_, copyright2,
  488.                CDF_NUMVARS_, &numVars2,
  489.                CDF_NUMATTRS_, &numAttrs2,
  490.                CDF_MAXREC_, &maxRec2,
  491.                CDF_VERSION_, &version2,
  492.                CDF_RELEASE_, &release2,
  493.                CDF_INCREMENT_, &increment2, 
  494.          NULL_);
  495. if (! StatusHandler("CDF2",status)) return FALSE;
  496.  
  497. if (! AttrNumberMatches()) return FALSE;
  498. if (! VarNumberMatches()) return FALSE;
  499.  
  500. /******************************************************************************
  501. * Compare CDFs.
  502. ******************************************************************************/
  503.  
  504. if (! CompareGeneral()) return FALSE;
  505. if (! CompareAttributes()) return FALSE;
  506. if (! CompareVariables()) return FALSE;
  507.  
  508. /******************************************************************************
  509. * Close CDFs.
  510. ******************************************************************************/
  511.  
  512. status = CDFclose (id1);
  513. if (! StatusHandler("CDF1",status)) return FALSE;
  514.  
  515. status = CDFclose (id2);
  516. if (! StatusHandler("CDF2",status)) return FALSE;
  517.  
  518. /******************************************************************************
  519. * If no differences, display message.
  520. ******************************************************************************/
  521.  
  522. if ( (! diffFound) && mLog) printf ("  No differences detected.\n");
  523.  
  524. return TRUE;    /* Successful comparison. */
  525. }
  526.  
  527. /******************************************************************************
  528. * CompareGeneral.
  529. ******************************************************************************/
  530.  
  531. Boolean CompareGeneral ()
  532. {
  533. int i, j;
  534.  
  535. if (numDims1 != numDims2) {
  536.   diffFound = TRUE;
  537.   printf ("    Different number of dimensions (%ld vs. %ld)\n",
  538.       numDims1, numDims2);
  539.   cmpVars = FALSE;
  540. }
  541. else {
  542.   if (numDims1 > 0)
  543.     for (i = 0; i < numDims1; i++)
  544.        if (dimSizes1[i] != dimSizes2[i]) {
  545.          diffFound = TRUE;
  546.          printf ("    Different dimension sizes (");
  547.      for (j = 0; j < numDims1; j++) printf ("%ld ", dimSizes1[j]);
  548.      printf ("vs.");
  549.      for (j = 0; j < numDims2; j++) printf (" %ld", dimSizes2[j]);
  550.      printf (")\n");
  551.      cmpVars = FALSE;
  552.      break;
  553.        }
  554. }
  555.  
  556. if (encoding1 != encoding2) {
  557.   diffFound = TRUE;
  558.   printf ("    Different encodings (%s vs. %s)\n",
  559.       EncodingToken(encoding1), EncodingToken(encoding2));
  560. }
  561.  
  562. if (majority1 != majority2) {
  563.   diffFound = TRUE;
  564.   printf ("    Different majorities (%s vs. %s)\n",
  565.       MajorityToken(majority1), MajorityToken(majority2));
  566. }
  567.  
  568. if (format1 != format2) {
  569.   diffFound = TRUE;
  570.   printf ("    Different formats (%s vs. %s)\n",
  571.       FormatToken(format1), FormatToken(format2));
  572. }
  573.  
  574. if (numVars1 != numVars2) {
  575.   diffFound = TRUE;
  576.   printf ("    Different number of variables (%ld vs. %ld)\n",
  577.       numVars1, numVars2);
  578. }
  579.  
  580. if (numAttrs1 != numAttrs2) {
  581.   diffFound = TRUE;
  582.   printf ("    Different number of attributes (%ld vs. %ld)\n",
  583.       numAttrs1, numAttrs2);
  584. }
  585.  
  586. if (maxRec1 != maxRec2) {
  587.   diffFound = TRUE;
  588.   printf ("    Different maximum record (%ld vs. %ld)\n",
  589.       maxRec1 + 1, maxRec2 + 1);
  590. }
  591.  
  592. if (version1 != version2 || release1 != release2 || increment1 != increment2) {
  593.   diffFound = TRUE;
  594.   printf ("    Different creation libraries (V%ld.%ld.%ld vs. V%ld.%ld.%ld)\n",
  595.       version1, release1, increment1, version2, release2, increment2);
  596. }
  597.  
  598. return TRUE;
  599. }
  600.  
  601. /******************************************************************************
  602. * AttrNumberMatches.  Determine attribute number matches.
  603. ******************************************************************************/
  604.  
  605. Boolean AttrNumberMatches ()
  606. {
  607. CDFstatus status;
  608. long attrN1, attrN2;
  609. char attrName[CDF_ATTR_NAME_LEN+1];
  610.  
  611. if (numAttrs1 > 0) {
  612.   MALLOC (attrNumMatches1, numAttrs1 * sizeof(long));
  613. }
  614. else
  615.   attrNumMatches1 = (long *) NULL;
  616.  
  617. for (attrN1 = 0; attrN1 < numAttrs1; attrN1++) {
  618.    status = CDFlib (SELECT_, CDF_, id1,
  619.                  ATTR_, attrN1,
  620.             GET_, ATTR_NAME_, attrName,
  621.             NULL_);
  622.    if (! StatusHandler("CDF1",status)) return FALSE;
  623.  
  624.    status = CDFlib (SELECT_, CDF_, id2,
  625.             GET_, ATTR_NUMBER_, attrName, &attrN2,
  626.             NULL_);
  627.    if (status == NO_SUCH_ATTR)
  628.      attrNumMatches1[attrN1] = -1;
  629.    else {
  630.      if (! StatusHandler("CDF2",status)) return FALSE;
  631.      attrNumMatches1[attrN1] = attrN2;
  632.    }
  633. }
  634.  
  635. if (numAttrs2 > 0) {
  636.   MALLOC (attrNumMatches2, numAttrs2 * sizeof(long));
  637. }
  638. else
  639.   attrNumMatches2 = (long *) NULL;
  640.  
  641. for (attrN2 = 0; attrN2 < numAttrs2; attrN2++) {
  642.    status = CDFlib (SELECT_, CDF_, id2,
  643.                  ATTR_, attrN2,
  644.             GET_, ATTR_NAME_, attrName,
  645.             NULL_);
  646.    if (! StatusHandler("CDF2",status)) return FALSE;
  647.  
  648.    status = CDFlib (SELECT_, CDF_, id1,
  649.             GET_, ATTR_NUMBER_, attrName, &attrN1,
  650.             NULL_);
  651.    if (status == NO_SUCH_ATTR)
  652.      attrNumMatches2[attrN2] = -1;
  653.    else {
  654.      if (! StatusHandler("CDF1",status)) return FALSE;
  655.      attrNumMatches2[attrN2] = attrN1;
  656.    }
  657. }
  658.  
  659. return TRUE;
  660. }
  661.  
  662. /******************************************************************************
  663. * VarNumberMatches.  Determine variable number matches.
  664. ******************************************************************************/
  665.  
  666. Boolean VarNumberMatches ()
  667. {
  668. CDFstatus status;
  669. long varN1, varN2;
  670. char varName[CDF_VAR_NAME_LEN+1];
  671.  
  672. if (numVars1 > 0) {
  673.   MALLOC (varNumMatches1, numVars1 * sizeof(long));
  674. }
  675. else
  676.   varNumMatches1 = (long *) NULL;
  677.  
  678. for (varN1 = 0; varN1 < numVars1; varN1++) {
  679.    status = CDFlib (SELECT_, CDF_, id1,
  680.                  VAR_, varN1,
  681.             GET_, VAR_NAME_, varName,
  682.             NULL_);
  683.    if (! StatusHandler("CDF1",status)) return FALSE;
  684.  
  685.    status = CDFlib (SELECT_, CDF_, id2,
  686.             GET_, VAR_NUMBER_, varName, &varN2,
  687.             NULL_);
  688.    if (status == NO_SUCH_VAR)
  689.      varNumMatches1[varN1] = -1;
  690.    else {
  691.      if (! StatusHandler("CDF2",status)) return FALSE;
  692.      varNumMatches1[varN1] = varN2;
  693.    }
  694. }
  695.  
  696. if (numVars2 > 0) {
  697.   MALLOC (varNumMatches2, numVars2 * sizeof(long));
  698. }
  699. else
  700.   varNumMatches2 = (long *) NULL;
  701.  
  702. for (varN2 = 0; varN2 < numVars2; varN2++) {
  703.    status = CDFlib (SELECT_, CDF_, id2,
  704.                  VAR_, varN2,
  705.             GET_, VAR_NAME_, varName,
  706.             NULL_);
  707.    if (! StatusHandler("CDF2",status)) return FALSE;
  708.  
  709.    status = CDFlib (SELECT_, CDF_, id1,
  710.             GET_, VAR_NUMBER_, varName, &varN1,
  711.             NULL_);
  712.    if (status == NO_SUCH_VAR)
  713.      varNumMatches2[varN2] = -1;
  714.    else {
  715.      if (! StatusHandler("CDF1",status)) return FALSE;
  716.      varNumMatches2[varN2] = varN1;
  717.    }
  718. }
  719.  
  720. return TRUE;
  721. }
  722.  
  723. /******************************************************************************
  724. * CompareAttributes.
  725. ******************************************************************************/
  726.  
  727. Boolean CompareAttributes ()
  728. {
  729. CDFstatus status;
  730. long attrN1, attrN2;
  731. char attrName[CDF_ATTR_NAME_LEN+1];
  732. Boolean cmpAttr;
  733.  
  734. if (cmpAttrs) {
  735.   for (attrN1 = 0; attrN1 < numAttrs1; attrN1++) {
  736.      if (attrNumMatches1[attrN1] == -1) {
  737.        status = CDFlib (SELECT_, CDF_, id1,
  738.                  ATTR_, attrN1,
  739.             GET_, ATTR_NAME_, attrName,
  740.             NULL_);
  741.        if (! StatusHandler("CDF1",status)) return FALSE;
  742.        diffFound = TRUE;
  743.        printf ("    Attribute %s does not exist in CDF2\n", attrName);
  744.      }
  745.      else {
  746.        status = CDFlib (SELECT_, CDF_, id1,
  747.                  ATTR_, attrN1,
  748.             GET_, ATTR_NAME_, attrName,
  749.                   ATTR_SCOPE_, &attrScope1,
  750.                   ATTR_MAXENTRY_, &attrMaxEntry1,
  751.                   ATTR_NUMENTRIES_, &attrNumEntries1,
  752.             NULL_);
  753.        if (! StatusHandler("CDF1",status)) return FALSE;
  754.  
  755.        status = CDFlib (SELECT_, CDF_, id2,
  756.                  ATTR_, attrNumMatches1[attrN1],
  757.             GET_, ATTR_SCOPE_, &attrScope2,
  758.                   ATTR_MAXENTRY_, &attrMaxEntry2,
  759.                   ATTR_NUMENTRIES_, &attrNumEntries2,
  760.             NULL_);
  761.        if (! StatusHandler("CDF2",status)) return FALSE;
  762.  
  763.        if (mLog) printf ("  Comparing attribute \"%s\"\n", attrName);
  764.  
  765.        cmpAttr = TRUE;
  766.  
  767.        if (cmpNumbers)
  768.          if (attrNumMatches1[attrN1] != attrN1) {
  769.            diffFound = TRUE;
  770.        printf ("    Different numbers for attribute %s (%ld vs. %ld)\n",
  771.            attrName, attrN1 + 1, attrNumMatches1[attrN1] + 1);
  772.      }
  773.  
  774.        if (attrScope1 != attrScope2) {
  775.          diffFound = TRUE;
  776.      printf ("    Different scopes for attribute %s (%s vs. %s)\n",
  777.          attrName, ScopeToken(attrScope1), ScopeToken(attrScope2));
  778.      cmpAttr = FALSE;
  779.        }
  780.  
  781.        if (attrMaxEntry1 != attrMaxEntry2) {
  782.          diffFound = TRUE;
  783.      printf
  784.          ("    Different maximum entry for attribute %s (%ld vs. %ld)\n",
  785.           attrName, attrMaxEntry1 + 1, attrMaxEntry2 + 1);
  786.        }
  787.  
  788.        if (attrNumEntries1 != attrNumEntries2) {
  789.          diffFound = TRUE;
  790.      printf ("    Different num. entries for attribute %s (%ld vs. %ld)\n",
  791.          attrName, attrNumEntries1, attrNumEntries2);
  792.        }
  793.  
  794.        if (cmpAttr) CompareAttributeEntries (attrN1, attrNumMatches1[attrN1],
  795.                          attrName);
  796.      }
  797.   }
  798.  
  799.   for (attrN2 = 0; attrN2 < numAttrs2; attrN2++)
  800.      if (attrNumMatches2[attrN2] == -1) {
  801.        status = CDFlib (SELECT_, CDF_, id2,
  802.                  ATTR_, attrN2,
  803.             GET_, ATTR_NAME_, attrName,
  804.             NULL_);
  805.        if (! StatusHandler("CDF2",status)) return FALSE;
  806.        diffFound = TRUE;
  807.        printf ("    Attribute %s does not exist in CDF1\n", attrName);
  808.      }
  809. }
  810.  
  811. return TRUE;
  812. }
  813.  
  814. /******************************************************************************
  815. * CompareAttributeEntries.
  816. ******************************************************************************/
  817.  
  818. Boolean CompareAttributeEntries (attrN1, attrN2, attrName)
  819. long attrN1;
  820. long attrN2;
  821. char *attrName;
  822. {
  823. CDFstatus status;
  824. char      varName[CDF_VAR_NAME_LEN+1];
  825. long      entryN;
  826. long      entryN1;
  827. long      entryN2;
  828.  
  829. status = CDFlib (SELECT_, CDF_, id1,
  830.               ATTR_, attrN1,
  831.          NULL_);
  832. if (! StatusHandler("CDF1",status)) return FALSE;
  833.  
  834. status = CDFlib (SELECT_, CDF_, id2,
  835.               ATTR_, attrN2,
  836.          NULL_);
  837. if (! StatusHandler("CDF2",status)) return FALSE;
  838.  
  839. if (attrScope1 == GLOBAL_SCOPE || attrScope1 == GLOBAL_SCOPE_ASSUMED) {
  840.   for (entryN = 0; entryN <= Maximum(attrMaxEntry1,attrMaxEntry2); entryN++)
  841.      CompareEntry (attrName, entryN, entryN, NULL);
  842. }
  843. else {
  844.   for (entryN1 = 0; entryN1 <= attrMaxEntry1; entryN1++)
  845.      if (entryN1 < numVars1)
  846.        if (varNumMatches1[entryN1] == -1) {
  847.          diffFound = TRUE;
  848.          printf ("    No corresponding variable in CDF2 for entry number");
  849.      printf (" %ld of attribute %s in CDF1\n", entryN1 + 1, attrName);
  850.        }
  851.        else {
  852.      status = CDFlib (SELECT_, CDF_, id1,
  853.                    VAR_, entryN1,
  854.               GET_, VAR_NAME_, varName,
  855.               NULL_);
  856.      if (! StatusHandler("CDF1",status)) return FALSE;
  857.      CompareEntry (attrName, entryN1, varNumMatches1[entryN1], varName);
  858.        }
  859.      else
  860.        CompareEntry (attrName, entryN1, entryN1, NULL); /* assume GLOBAL? */
  861.  
  862.   for (entryN2 = 0; entryN2 <= attrMaxEntry2; entryN2++)
  863.      if (entryN2 < numVars2) {
  864.        if (varNumMatches2[entryN2] == -1) {
  865.          diffFound = TRUE;
  866.          printf ("    No corresponding variable in CDF1 for entry number");
  867.      printf (" %ld of attribute %s in CDF2\n", entryN2 + 1, attrName);
  868.        }
  869.      }
  870.      else
  871.        CompareEntry (attrName, entryN2, entryN2, NULL); /* assume GLOBAL? */
  872. }
  873. return TRUE;
  874. }
  875.  
  876. /******************************************************************************
  877. * CompareEntry.    It is assumed that the attribute has already been selected
  878. *           in the two CDFs.
  879. ******************************************************************************/
  880.  
  881. Boolean CompareEntry (attrName, entryN1, entryN2, varName)
  882. char *attrName;
  883. long entryN1;
  884. long entryN2;
  885. char *varName;        /* if == NULL, then GLOBAL scope attribute and the
  886.                entry numbers are assumed to be the same,
  887.                if != NULL, then VARIABLE scope attribute and
  888.                this is the associated variable for these entries */
  889. {
  890. CDFstatus status;
  891. CDFstatus status1;
  892. CDFstatus status2;
  893. long      entryDataType1, entryDataType2;
  894. long      entryNumElems1, entryNumElems2;
  895. void      *entryValue1, *entryValue2;
  896. char      varNameField[CDF_VAR_NAME_LEN+13];
  897. char      entryNumField[12];
  898. long      Nbytes;
  899.  
  900. if (varName == NULL) {
  901.   varNameField[0] = '\0';
  902.   sprintf (entryNumField, "%ld", entryN1);
  903. }
  904. else {
  905.   strcpy (varNameField, " (variable ");
  906.   strcat (varNameField, varName);
  907.   strcat (varNameField, ")");
  908.   if (entryN1 == entryN2)
  909.     sprintf (entryNumField, "%ld", entryN1);
  910.   else
  911.     sprintf (entryNumField, "%ld/%ld", entryN1, entryN2);
  912. }
  913.  
  914. status1 = CDFlib (SELECT_, CDF_, id1,
  915.                ENTRY_, entryN1,
  916.           GET_, ENTRY_DATATYPE_, &entryDataType1,
  917.             ENTRY_NUMELEMS_, &entryNumElems1,
  918.           NULL_);
  919. status2 = CDFlib (SELECT_, CDF_, id2,
  920.                ENTRY_, entryN2,
  921.           GET_, ENTRY_DATATYPE_, &entryDataType2,
  922.             ENTRY_NUMELEMS_, &entryNumElems2,
  923.           NULL_);
  924.  
  925. if (status1 == NO_SUCH_ENTRY && status2 == NO_SUCH_ENTRY) return TRUE;
  926.  
  927. if (status1 == NO_SUCH_ENTRY) {
  928.   diffFound = TRUE;
  929.   printf ("    No entry number %ld%s for attribute %s in CDF1\n",
  930.       entryN1 + 1, varNameField, attrName);
  931.   return TRUE;
  932. }
  933.  
  934. if (status2 == NO_SUCH_ENTRY) {
  935.   diffFound = TRUE;
  936.   printf ("    No entry number %ld%s for attribute %s in CDF2\n",
  937.       entryN2 + 1, varNameField, attrName);
  938.   return TRUE;
  939. }
  940.  
  941. if (! StatusHandler("CDF1",status1)) return FALSE;
  942. if (! StatusHandler("CDF2",status2)) return FALSE;
  943.  
  944. if (entryDataType1 != entryDataType2) {
  945.   diffFound = TRUE;
  946.   printf ("    Different data types for entry number %s%s of attribute %s ",
  947.        entryNumField, varNameField, attrName);
  948.   printf ("(%s vs. %s)\n",
  949.       DataTypeToken(entryDataType1), DataTypeToken(entryDataType2));
  950.   /* DON'T RETURN IF THIS DIFFERENCE FOUND */
  951. }
  952.  
  953. if ( ! EquivalentDataTypes(entryDataType1,entryDataType2)) {
  954.   diffFound = TRUE;
  955.   printf
  956.       ("    Non-equivalent data types for entry number %s%s of attribute %s ",
  957.        entryNumField, varNameField, attrName);
  958.   printf ("(%s vs. %s)\n",
  959.       DataTypeToken(entryDataType1), DataTypeToken(entryDataType2));
  960.   return TRUE;
  961. }
  962.  
  963. if (entryNumElems1 != entryNumElems2) {
  964.   diffFound = TRUE;
  965.   printf ("    Different number of elements for entry number %s",
  966.       entryNumField);
  967.   printf ("%s of attribute %s (%ld vs. %ld)\n", varNameField,
  968.       attrName, entryNumElems1, entryNumElems2);
  969.   return TRUE;
  970. }
  971.  
  972. Nbytes = entryNumElems1 * DataTypeSize(entryDataType1);
  973.  
  974. MALLOC (entryValue1, Nbytes);
  975. MALLOC (entryValue2, Nbytes);
  976.  
  977. status = CDFlib (SELECT_, CDF_, id1,
  978.          GET_, ENTRY_DATA_, entryValue1,
  979.          NULL_);
  980. if (! StatusHandler("CDF1",status)) return FALSE;
  981.  
  982. status = CDFlib (SELECT_, CDF_, id2,
  983.          GET_, ENTRY_DATA_, entryValue2,
  984.          NULL_);
  985. if (! StatusHandler("CDF2",status)) return FALSE;
  986.  
  987. if (memcmp(entryValue1,entryValue2,Nbytes) != 0) {
  988.   diffFound = TRUE;
  989.   printf ("    Different values for entry number %s%s of attribute %s\n",
  990.       entryNumField, varNameField, attrName);
  991. }
  992.  
  993. free (entryValue1);
  994. free (entryValue2);
  995.  
  996. return TRUE;
  997. }
  998.  
  999. /******************************************************************************
  1000. * CompareVariables.
  1001. ******************************************************************************/
  1002.  
  1003. Boolean CompareVariables ()
  1004. {
  1005. CDFstatus status;
  1006. long varN1, varN2;
  1007. char varName[CDF_VAR_NAME_LEN + 1];
  1008. Boolean cmpVar;
  1009. int i, j;
  1010.  
  1011. if (cmpVars) {
  1012.   for (varN1 = 0; varN1 < numVars1; varN1++) {
  1013.      if (varNumMatches1[varN1] == -1) {
  1014.        status = CDFlib (SELECT_, CDF_, id1,
  1015.                  VAR_, varN1,
  1016.             GET_, VAR_NAME_, varName,
  1017.             NULL_);
  1018.        if (! StatusHandler("CDF1",status)) return FALSE;
  1019.        diffFound = TRUE;
  1020.        printf ("    Variable %s does not exist in CDF2\n", varName);
  1021.      }
  1022.      else {
  1023.        status = CDFlib (SELECT_, CDF_, id1,
  1024.                  VAR_, varN1,
  1025.             GET_, VAR_NAME_, varName,
  1026.                   VAR_DATATYPE_, &varDataType1,
  1027.                   VAR_NUMELEMS_, &varNumElems1,
  1028.                   VAR_RECVARY_, &varRecVary1,
  1029.                   VAR_DIMVARYS_, varDimVarys1,
  1030.                   VAR_MAXREC_, &varMaxRec1,
  1031.                   VAR_EXTENDRECS_, &varExtendRecs1,
  1032.             NULL_);
  1033.        if (! StatusHandler("CDF1",status)) return FALSE;
  1034.  
  1035.        status = CDFlib (SELECT_, CDF_, id2,
  1036.                  VAR_, varNumMatches1[varN1],
  1037.             GET_, VAR_DATATYPE_, &varDataType2,
  1038.                   VAR_NUMELEMS_, &varNumElems2,
  1039.                   VAR_RECVARY_, &varRecVary2,
  1040.                   VAR_DIMVARYS_, varDimVarys2,
  1041.                   VAR_MAXREC_, &varMaxRec2,
  1042.                   VAR_EXTENDRECS_, &varExtendRecs2,
  1043.             NULL_);
  1044.        if (! StatusHandler("CDF2",status)) return FALSE;
  1045.  
  1046.        if (mLog) printf ("  Comparing variable \"%s\"\n", varName);
  1047.  
  1048.        cmpVar = TRUE;
  1049.  
  1050.        if (cmpNumbers)
  1051.          if (varNumMatches1[varN1] != varN1) {
  1052.            diffFound = TRUE;
  1053.        printf ("    Different numbers for variable %s (%ld vs. %ld)\n",
  1054.            varName, varN1 + 1, varNumMatches1[varN1] + 1);
  1055.      }
  1056.  
  1057.        if (varDataType1 != varDataType2) {
  1058.          diffFound = TRUE;
  1059.      printf ("    Different data types for variable %s (%s vs. %s)\n",
  1060.          varName, DataTypeToken(varDataType1),
  1061.          DataTypeToken(varDataType2));
  1062.      /* STILL MIGHT BE ABLE TO COMPARE VARIABLES. */
  1063.        }
  1064.  
  1065.        if ( ! EquivalentDataTypes(varDataType1,varDataType2)) {
  1066.          diffFound = TRUE;
  1067.      printf ("    Non-equivalent data types for variable %s (%s vs. %s)\n",
  1068.          varName, DataTypeToken(varDataType1),
  1069.          DataTypeToken(varDataType2));
  1070.      cmpVar = FALSE;
  1071.        }
  1072.  
  1073.        if (varNumElems1 != varNumElems2) {
  1074.          diffFound = TRUE;
  1075.      printf
  1076.        ("    Different number of elements for variable %s (%ld vs. %ld)\n",
  1077.         varName, varNumElems1, varNumElems2);
  1078.      cmpVar = FALSE;
  1079.        }
  1080.  
  1081.        if (varRecVary1 != varRecVary2) {
  1082.          diffFound = TRUE;
  1083.      printf
  1084.          ("    Different record variances for variable %s (%s vs. %s)\n",
  1085.           varName, VarianceToken(varRecVary1), VarianceToken(varRecVary2));
  1086.        }
  1087.  
  1088.        for (i = 0; i < numDims1; i++)
  1089.          if (varDimVarys1[i] != varDimVarys2[i]) {
  1090.            diffFound = TRUE;
  1091.            printf ("    Different dimension variances for variable %s (",
  1092.            varName);
  1093.            for (j = 0; j < numDims1; j++)
  1094.           printf ("%ld ", VarianceToken(varDimVarys1[j]));
  1095.        printf ("vs.");
  1096.        for (j = 0; j < numDims2; j++)
  1097.           printf (" %ld", VarianceToken(varDimVarys2[j]));
  1098.        printf (")\n");
  1099.        break;
  1100.          }
  1101.  
  1102.        if (varMaxRec1 != varMaxRec2) {
  1103.          diffFound = TRUE;
  1104.      printf("    Different maximum record for variable %s (%ld vs. %ld)\n",
  1105.         varName, varMaxRec1 + 1, varMaxRec2 + 1);
  1106.        }
  1107.  
  1108.        if (varExtendRecs1 != varExtendRecs2) {
  1109.          diffFound = TRUE;
  1110.      printf("    Different extend records for variable %s (%ld vs. %ld)\n",
  1111.         varName, varExtendRecs1, varExtendRecs2);
  1112.        }
  1113.  
  1114.        if (cmpVar) CompareVariableValues (varN1, varNumMatches1[varN1],
  1115.                       varName);
  1116.      }
  1117.   }
  1118.  
  1119.   for (varN2 = 0; varN2 < numVars2; varN2++)
  1120.      if (varNumMatches2[varN2] == -1) {
  1121.        status = CDFlib (SELECT_, CDF_, id2,
  1122.                  VAR_, varN2,
  1123.             GET_, VAR_NAME_, varName,
  1124.             NULL_);
  1125.        if (! StatusHandler("CDF2",status)) return FALSE;
  1126.        diffFound = TRUE;
  1127.        printf ("    Varibute %s does not exist in CDF1\n", varName);
  1128.      }
  1129. }
  1130.  
  1131. return TRUE;
  1132. }
  1133.  
  1134. /******************************************************************************
  1135. * CompareVariableValues.
  1136. ******************************************************************************/
  1137.  
  1138. Boolean CompareVariableValues (varN1, varN2, varName)
  1139. long varN1;
  1140. long varN2;
  1141. char *varName;
  1142. {
  1143. void *buffer1;
  1144. void *buffer2;
  1145. void *bufferX;                /* Buffer with majority switched. */
  1146. void *bufferZ;                /* Buffer with which to compare. */
  1147. void *fillValue1;
  1148. void *fillValue2;
  1149. CDFstatus status, status1, status2;
  1150. long NrecBytes, NvalueBytes, NrecValues;
  1151. long dimN, valueN, recN;
  1152. long maxRec;
  1153. enum flipENUM {noFLIP_,ROWtoCOL_,COLtoROW_} flip;
  1154. enum accTypeENUM {HYP,SEQ,SIN} accType;
  1155. static long HYPindices[CDF_MAX_DIMS] = {0,0,0,0,0,0,0,0,0,0};
  1156. static long HYPcounts[CDF_MAX_DIMS];
  1157. static long HYPintervals[CDF_MAX_DIMS] = {1,1,1,1,1,1,1,1,1,1};
  1158. static long SEQindices[CDF_MAX_DIMS] = {0,0,0,0,0,0,0,0,0,0};
  1159. static long SINcounts[CDF_MAX_DIMS];
  1160. long indices[CDF_MAX_DIMS];
  1161.  
  1162. /******************************************************************************
  1163. * Select variables.
  1164. ******************************************************************************/
  1165.  
  1166. status = CDFlib (SELECT_, CDF_, id1,
  1167.               VAR_, varN1,
  1168.          NULL_);
  1169. if (! StatusHandler("CDF1",status)) return FALSE;
  1170.  
  1171. status = CDFlib (SELECT_, CDF_, id2,
  1172.               VAR_, varN2,
  1173.          NULL_);
  1174. if (! StatusHandler("CDF2",status)) return FALSE;
  1175.  
  1176. /******************************************************************************
  1177. * Compare fill values.
  1178. ******************************************************************************/
  1179.  
  1180. NvalueBytes = varNumElems1 * DataTypeSize(varDataType1);
  1181.  
  1182. MALLOC (fillValue1, NvalueBytes);
  1183. MALLOC (fillValue2, NvalueBytes);
  1184.  
  1185. status1 = CDFlib (SELECT_, CDF_, id1,
  1186.           GET_, VAR_FILLVALUE_, fillValue1,
  1187.           NULL_);
  1188. status2 = CDFlib (SELECT_, CDF_, id2,
  1189.           GET_, VAR_FILLVALUE_, fillValue2,
  1190.           NULL_);
  1191.  
  1192. if (status1 != NO_FILLVALUE_SPECIFIED) {
  1193.   if (! StatusHandler("CDF1",status1)) return FALSE;
  1194.   if (status2 != NO_FILLVALUE_SPECIFIED) {
  1195.     if (! StatusHandler("CDF2",status2)) return FALSE;
  1196.     if (memcmp(fillValue1,fillValue2,NvalueBytes) != 0) {
  1197.       diffFound = TRUE;
  1198.       printf ("    Different fill values for variable %s\n", varName);
  1199.     }
  1200.   }
  1201.   else {
  1202.     diffFound = TRUE;
  1203.     printf ("    No fill value for variable %s in CDF2\n", varName);
  1204.   }
  1205. }
  1206. else {
  1207.   if (status2 != NO_FILLVALUE_SPECIFIED) {
  1208.     if (! StatusHandler("CDF2",status2)) return FALSE;
  1209.     diffFound = TRUE;
  1210.     printf ("    No fill value for variable %s in CDF1\n", varName);
  1211.   }
  1212. }
  1213.  
  1214. free (fillValue1);
  1215. free (fillValue2);
  1216.  
  1217. /******************************************************************************
  1218. * Calculate number of values/bytes per record.
  1219. ******************************************************************************/
  1220.  
  1221. NrecValues = 1;
  1222.  
  1223. if (numDims1 > 0)
  1224.   for (dimN = 0; dimN < numDims1; dimN++)
  1225.      if (varDimVarys1[dimN] ||
  1226.      varDimVarys2[dimN]) NrecValues *= dimSizes1[dimN];
  1227.  
  1228. NrecBytes = NrecValues * NvalueBytes;
  1229.  
  1230. /******************************************************************************
  1231. * Determine type of access.
  1232. ******************************************************************************/
  1233.  
  1234. switch (numDims1) {
  1235.   case 0:
  1236.     if (varRecVary1 == varRecVary2 && varMaxRec1 == varMaxRec2)
  1237.       accType = SEQ;
  1238.     else
  1239.       accType = SIN;
  1240.     MALLOC (buffer1, NvalueBytes);
  1241.     MALLOC (buffer2, NvalueBytes);
  1242.  
  1243.     break;
  1244.  
  1245.   case 1:
  1246. #if defined(__MSDOS__)
  1247.     if (NrecBytes > (long) 65535) {
  1248.       if (SameVarys(numDims1,varRecVary1,varRecVary2,
  1249.             varDimVarys1,varDimVarys2) && varMaxRec1 == varMaxRec2)
  1250.     accType = SEQ;
  1251.       else
  1252.     accType = SIN;
  1253.       MALLOC (buffer1, NvalueBytes);
  1254.       MALLOC (buffer2, NvalueBytes);
  1255.     }
  1256.     else {
  1257. #endif
  1258.       buffer1 = (void *) malloc (NrecBytes);
  1259.       buffer2 = (void *) malloc (NrecBytes);
  1260.  
  1261.       if (buffer1 == NULL || buffer2 == NULL) {
  1262.         if (buffer1 != NULL) free (buffer1);
  1263.         if (buffer2 != NULL) free (buffer2);
  1264.  
  1265.         if (SameVarys(numDims1,varRecVary1,varRecVary2,
  1266.               varDimVarys1,varDimVarys2) && varMaxRec1 == varMaxRec2)
  1267.       accType = SEQ;
  1268.         else
  1269.       accType = SIN;
  1270.  
  1271.         MALLOC (buffer1, NvalueBytes);
  1272.         MALLOC (buffer2, NvalueBytes);
  1273.       }
  1274.       else {
  1275.         accType = HYP;
  1276.         flip = noFLIP_;        /* Majority doesn't matter if 1-dimensional. */
  1277.       }
  1278. #if defined(__MSDOS__)
  1279.     }
  1280. #endif
  1281.  
  1282.     break;
  1283.  
  1284.   default:
  1285. #if defined(__MSDOS__)
  1286.     if (NrecBytes > (long) 65535) {
  1287.       if (SameVarys(numDims1,varRecVary1,varRecVary2,
  1288.             varDimVarys1,varDimVarys2) && majority1 == majority2 &&
  1289.                              varMaxRec1 == varMaxRec2)
  1290.     accType = SEQ;
  1291.       else
  1292.     accType = SIN;
  1293.       MALLOC (buffer1, NvalueBytes);
  1294.       MALLOC (buffer2, NvalueBytes);
  1295.     }
  1296.     else {
  1297. #endif
  1298.       buffer1 = (void *) malloc (NrecBytes);
  1299.       buffer2 = (void *) malloc (NrecBytes);
  1300.       if (majority1 != majority2) bufferX = (void *) malloc (NrecBytes);
  1301.  
  1302.       if (buffer1 == NULL || buffer2 == NULL ||
  1303.       (majority1 != majority2 && bufferX == NULL)) {
  1304.         if (buffer1 != NULL) free (buffer1);
  1305.         if (buffer2 != NULL) free (buffer2);
  1306.         if (majority1 != majority2 && bufferX != NULL) free (bufferX);
  1307.  
  1308.         if (SameVarys(numDims1,varRecVary1,varRecVary2,
  1309.               varDimVarys1,varDimVarys2) &&
  1310.         majority1 == majority2 && varMaxRec1 == varMaxRec2)
  1311.       accType = SEQ;
  1312.         else
  1313.       accType = SIN;
  1314.         MALLOC (buffer1, NvalueBytes);
  1315.         MALLOC (buffer2, NvalueBytes);
  1316.       }
  1317.       else {
  1318.         accType = HYP;
  1319.         if (majority1 == majority2)
  1320.       flip = noFLIP_;
  1321.         else
  1322.       if (majority1 == ROW_MAJOR)
  1323.         flip = ROWtoCOL_;
  1324.       else
  1325.         flip = COLtoROW_;
  1326.       }
  1327. #if defined(__MSDOS__)
  1328.     }
  1329. #endif
  1330.  
  1331.     break;
  1332. }
  1333.  
  1334. /******************************************************************************
  1335. * Compare variable values.
  1336. ******************************************************************************/
  1337.  
  1338. switch (accType) {
  1339.   case HYP:
  1340.     /***********************************************************************
  1341.     * Use hyper reads/writes.
  1342.     ***********************************************************************/
  1343.  
  1344.     if (mLog) printf ("    (comparing values with hyper reads/writes)\n");
  1345.  
  1346.     for (dimN = 0; dimN < numDims1; dimN++)
  1347.        if (varDimVarys1[dimN] || varDimVarys2[dimN])
  1348.      HYPcounts[dimN] = dimSizes1[dimN];
  1349.        else
  1350.      HYPcounts[dimN] = 1;
  1351.  
  1352.     status = CDFlib (SELECT_, CDF_, id1,
  1353.                   CDF_RECCOUNT_, (long) 1,
  1354.                   CDF_RECINTERVAL_, (long) 1,
  1355.                   CDF_DIMINDICES_, HYPindices,
  1356.                   CDF_DIMCOUNTS_, HYPcounts,
  1357.                   CDF_DIMINTERVALS_, HYPintervals,
  1358.              NULL_);
  1359.     if (! StatusHandler("CDF1",status)) return FALSE;
  1360.  
  1361.     status = CDFlib (SELECT_, CDF_, id2,
  1362.                   CDF_RECCOUNT_, (long) 1,
  1363.                   CDF_RECINTERVAL_, (long) 1,
  1364.                   CDF_DIMINDICES_, HYPindices,
  1365.                   CDF_DIMCOUNTS_, HYPcounts,
  1366.                   CDF_DIMINTERVALS_, HYPintervals,
  1367.              NULL_);
  1368.     if (! StatusHandler("CDF2",status)) return FALSE;
  1369.  
  1370.     maxRec = Maximum (varMaxRec1, varMaxRec2);
  1371.  
  1372.     for (recN = 0; recN <= maxRec; recN++) {
  1373.        status = CDFlib (SELECT_, CDF_, id1,
  1374.                  CDF_RECNUMBER_, recN,
  1375.             GET_, VAR_HYPERDATA_, buffer1,
  1376.             NULL_);
  1377.        if (! StatusHandler("CDF1",status)) return FALSE;
  1378.  
  1379.        status = CDFlib (SELECT_, CDF_, id2,
  1380.                  CDF_RECNUMBER_, recN,
  1381.             GET_, VAR_HYPERDATA_, buffer2,
  1382.             NULL_);
  1383.        if (! StatusHandler("CDF2",status)) return FALSE;
  1384.  
  1385.        switch (flip) {
  1386.      case ROWtoCOL_:
  1387.        ROWtoCOL (buffer1, bufferX, numDims1, HYPcounts, NvalueBytes);
  1388.        bufferZ = bufferX;
  1389.        break;
  1390.      case COLtoROW_:
  1391.        COLtoROW (buffer1, bufferX, numDims1, HYPcounts, NvalueBytes);
  1392.        bufferZ = bufferX;
  1393.        break;
  1394.      case noFLIP_:
  1395.        bufferZ = buffer1;
  1396.        break;
  1397.        }
  1398.  
  1399.        if (memcmp(bufferZ,buffer2,NrecBytes) != 0) {
  1400.      printf ("      Difference in record %ld for variable %s",
  1401.          recN + 1, varName);
  1402.      printf (" (next...)\n");
  1403.      break;                /* Stop comparing records. */
  1404.        }
  1405.     }
  1406.  
  1407.     free (buffer1);
  1408.     free (buffer2);
  1409.     if (majority1 != majority2) free (bufferX);
  1410.  
  1411.     break;
  1412.  
  1413.   case SEQ:
  1414.     /***********************************************************************
  1415.     * Use sequential reads/writes.  Sequential access should only be used
  1416.     * if the variables are physically identical.
  1417.     ***********************************************************************/
  1418.  
  1419.     if (mLog) printf ("    (comparing values with sequential reads/writes)\n");
  1420.  
  1421.     status = CDFlib (SELECT_, CDF_, id1,
  1422.                   VAR_SEQPOS_, (long) 0, SEQindices,
  1423.              NULL_);
  1424.     if (! StatusHandler("CDF1",status)) return FALSE;
  1425.  
  1426.     status = CDFlib (SELECT_, CDF_, id2,
  1427.                   VAR_SEQPOS_, (long) 0, SEQindices,
  1428.              NULL_);
  1429.     if (! StatusHandler("CDF2",status)) return FALSE;
  1430.  
  1431.     status1 = CDFlib (SELECT_, CDF_, id1,
  1432.               GET_, VAR_SEQDATA_, buffer1,
  1433.               NULL_);
  1434.     status2 = CDFlib (SELECT_, CDF_, id2,
  1435.               GET_, VAR_SEQDATA_, buffer2,
  1436.               NULL_);
  1437.     while (status1 >= CDF_OK && status2 >= CDF_OK) {
  1438.       if (memcmp(buffer1,buffer2,NvalueBytes) != 0) {
  1439.     printf ("      Difference found for variable %s", varName);
  1440.     printf (" (next...)\n");
  1441.     free (buffer1);            /* Stop comparing records. */
  1442.     free (buffer2);
  1443.     return TRUE;
  1444.       }
  1445.  
  1446.       status1 = CDFlib (SELECT_, CDF_, id1,
  1447.             GET_, VAR_SEQDATA_, buffer1,
  1448.             NULL_);
  1449.       status2 = CDFlib (SELECT_, CDF_, id2,
  1450.             GET_, VAR_SEQDATA_, buffer2,
  1451.             NULL_);
  1452.     }
  1453.     if (status1 != END_OF_VAR)
  1454.       if (! StatusHandler("CDF1",status)) return FALSE;
  1455.     if (status2 != END_OF_VAR)
  1456.       if (! StatusHandler("CDF2",status)) return FALSE;
  1457.  
  1458.     free (buffer1);
  1459.     free (buffer2);
  1460.  
  1461.     break;
  1462.  
  1463.   case SIN:
  1464.     /***********************************************************************
  1465.     * Use Single reads/writes.  Note that 0-dimensional CDFs are possible
  1466.     * here.  (If so, anything involving dimension indices, counts, etc. does
  1467.     * not necessarily apply.  Since a 0-dimensional CDF here is unlikely,
  1468.     * checking for that case is not done to save the overhead for multi-
  1469.     * dimensional CDFs).
  1470.     ***********************************************************************/
  1471.  
  1472.     if (mLog) printf ("    (comparing values with single reads/writes)\n");
  1473.  
  1474.     for (dimN = 0; dimN < numDims1; dimN++)
  1475.        if (varDimVarys1[dimN] || varDimVarys2[dimN])
  1476.      SINcounts[dimN] = dimSizes1[dimN];
  1477.        else
  1478.      SINcounts[dimN] = 1;
  1479.  
  1480.     maxRec = Maximum (varMaxRec1, varMaxRec2);
  1481.  
  1482.     for (recN = 0; recN <= maxRec; recN++) {
  1483.        for (dimN = 0; dimN < numDims1; dimN++) indices[dimN] = 0;
  1484.  
  1485.        status = CDFlib (SELECT_, CDF_, id1,
  1486.                  CDF_RECNUMBER_, recN,
  1487.             NULL_);
  1488.        if (! StatusHandler("CDF1",status)) return FALSE;
  1489.  
  1490.        status = CDFlib (SELECT_, CDF_, id2,
  1491.                  CDF_RECNUMBER_, recN,
  1492.             NULL_);
  1493.        if (! StatusHandler("CDF2",status)) return FALSE;
  1494.  
  1495.        for (valueN = 0; valueN < NrecValues; valueN++) {
  1496.       status = CDFlib (SELECT_, CDF_, id1,
  1497.                     CDF_DIMINDICES_, indices,
  1498.                GET_, VAR_DATA_, buffer1,
  1499.                NULL_);
  1500.       if (! StatusHandler("CDF1",status)) return FALSE;
  1501.  
  1502.       status = CDFlib (SELECT_, CDF_, id2,
  1503.                     CDF_DIMINDICES_, indices,
  1504.                GET_, VAR_DATA_, buffer2,
  1505.                NULL_);
  1506.       if (! StatusHandler("CDF2",status)) return FALSE;
  1507.  
  1508.       if (memcmp(buffer1,buffer2,NvalueBytes) != 0) {
  1509.         printf ("      Difference in record %ld for variable %s",
  1510.             recN + 1, varName);
  1511.         printf (" (next...)\n");
  1512.         free (buffer1);
  1513.         free (buffer2);
  1514.         return TRUE;
  1515.       }
  1516.  
  1517.       if (majority1 == ROW_MAJOR) {
  1518.         INCRindicesROW (numDims1, SINcounts, indices);
  1519.       }
  1520.       else {
  1521.         INCRindicesCOL (numDims1, SINcounts, indices);
  1522.       }
  1523.        }
  1524.     }
  1525.  
  1526.     free (buffer1);
  1527.     free (buffer2);
  1528.  
  1529.     break;
  1530. }
  1531.  
  1532. return TRUE;
  1533. }
  1534.  
  1535. /******************************************************************************
  1536. * CleanupComparison.
  1537. ******************************************************************************/
  1538.  
  1539. void CleanupComparison ()
  1540. {
  1541. CDFclose (id1);
  1542. CDFclose (id2);
  1543.  
  1544. if (attrNumMatches1 != NULL) free (attrNumMatches1);
  1545. if (attrNumMatches2 != NULL) free (attrNumMatches2);
  1546.  
  1547. if (varNumMatches1 != NULL) free (varNumMatches1);
  1548. if (varNumMatches2 != NULL) free (varNumMatches2);
  1549.  
  1550. return;
  1551. }
  1552.  
  1553.  
  1554. /******************************************************************************
  1555. * SameVarys.
  1556. ******************************************************************************/
  1557.  
  1558. Boolean SameVarys (numDims, recVary1, recVary2, dimVarys1, dimVarys2)
  1559. long numDims;
  1560. long recVary1;
  1561. long recVary2;
  1562. long dimVarys1[];
  1563. long dimVarys2[];
  1564. {
  1565. int dimNum;
  1566.  
  1567. if (recVary1 != recVary2) return FALSE;
  1568.  
  1569. for (dimNum = 0; dimNum < numDims; dimNum++)
  1570.    if (dimVarys1[dimNum] != dimVarys2[dimNum]) return FALSE;
  1571.  
  1572. return TRUE;
  1573. }
  1574.  
  1575.  
  1576. /******************************************************************************
  1577. * EquivalentDataTypes.
  1578. ******************************************************************************/
  1579.  
  1580. Boolean EquivalentDataTypes (dataType1, dataType2)
  1581. long dataType1;
  1582. long dataType2;
  1583. {
  1584. static long realDataType[] = {0,1,2,0,3,0,0,0,0,0,
  1585.                   0,4,5,0,6,0,0,0,0,0,
  1586.                   0,7,8,0,0,0,0,0,0,0,
  1587.                   0,8,0,0,0,0,0,0,0,0,
  1588.                   0,1,0,0,7,8,0,0,0,0,
  1589.                   0,9,9,0,0,0,0,0,0,0};
  1590. if (realDataType[dataType1] == realDataType[dataType2])
  1591.   return TRUE;
  1592. else
  1593.   return FALSE;
  1594. }
  1595.  
  1596. /******************************************************************************
  1597. * DataTypeSize.  Return size (bytes) of a data type.
  1598. ******************************************************************************/
  1599.  
  1600. long DataTypeSize(dataType)
  1601. long dataType;
  1602. {
  1603. switch (dataType) {
  1604.   case CDF_BYTE: return 1;
  1605.   case CDF_INT1: return 1;
  1606.   case CDF_INT2: return 2;
  1607.   case CDF_INT4: return 4;
  1608.   case CDF_UINT1: return 1;
  1609.   case CDF_UINT2: return 2;
  1610.   case CDF_UINT4: return 4;
  1611.   case CDF_REAL4: return 4;
  1612.   case CDF_REAL8: return 8;
  1613.   case CDF_FLOAT: return 4;
  1614.   case CDF_DOUBLE: return 8;
  1615.   case CDF_EPOCH: return 8;
  1616.   case CDF_CHAR: return 1;
  1617.   case CDF_UCHAR: return 1;
  1618. }
  1619. return 0;
  1620. }
  1621.  
  1622. /******************************************************************************
  1623. * StatusHandler.
  1624. ******************************************************************************/
  1625.  
  1626. Boolean StatusHandler(which, status)
  1627. char *which;
  1628. CDFstatus status;
  1629. {
  1630. char text[CDF_STATUSTEXT_LEN + 1];
  1631.  
  1632. if (status == CDF_OK) return TRUE;        /* Do nothing. */
  1633.  
  1634. CDFlib (SELECT_, CDF_STATUS_, status,
  1635.     GET_, STATUS_TEXT_, text,
  1636.     NULL_);
  1637.  
  1638. if (status < CDF_WARN) {
  1639.   printf ("  ERROR, %s> %s\n", which, text);
  1640.   return FALSE;
  1641. }
  1642. else {
  1643.   if (mLog)
  1644.     if (status < CDF_OK)
  1645.       printf ("  WARNING, %s> %s\n", which, text);
  1646.     else
  1647.       printf ("  INFO, %s> %s\n", which, text);
  1648.   return TRUE;
  1649. }
  1650. }
  1651.